home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: MegaDisc
/
MegaDisc 24 (1991-10)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).zip
/
MegaDisc 24 (1991-10)(MegaDisc Digital Publishing)(AU)(Disk 2 of 2).adf
/
ART_GALLERY
/
nick.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-09-26
|
31KB
|
978 lines
/* Fractal NICK - by Dave Lyneham, 1991. */
/* Compile me with:
lc -Lm -cusf nick.c
*/
/* If you are interested in any part of this program, how it works etc,
please contact me:
(002) 23 4449
49 Fitzroy Crescent,
DYNNYRNE,
TAS 7004.
*/
/* This program makes use of transformation matrices and bit planes to
plot the affine transformations needed to spell out the word NICK as a
fractal.
The process takes a couple of hours to run its course (on an A500 with no
special hardware) */
/* The way it works is well written about in the book 'Fractals Everywhere'.
The method I am using is called the detirministic approach to fractal
generation, in which a grid or bit plane is progressively manipulated
by a series of well chosen 'affine' transformations until the designed
shape appears.
An affine transformation is any LINEAR action that can be done to a
two dimensional surface to change it.
A rotation is an affine transformation; as is a scaling: making it
bigger or smaller. A translation (ie: moving it about in an X or Y
direction) is also affine. A 'shear', an action that skews a square into
a kite shape is another of these transformations.
The affine transformations I have chosen below I have done so very
carefully. You will note that there are 13 of them. Now consider the
word NICK:
0 2 333 56666668 10 11
01 2 5 8 10 11
0 1 2 4 5 8 10 11
0 1 2 4 5 10 11
0 1 2 4 5 10 11
0 1 2 4 5 1011
0 1 2 4 5 1012
0 1 2 4 5 10 12
0 1 2 4 5 10 12
0 1 2 4 5 9 10 12
0 12 4 5 9 10 12
0 2 4 57777779 10 12
The way it is drawn there are 13 different shapes that make up the word.
The 13 transformations correspond to the 13 shapes of the word NICK.
The secret to chosing the right affine transformations is to consider the
final shape that will result from the process of drawing the word- in
this case the result will be roughly a rectangle of these dimensions:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
X X
X X
X X
X X
X X
X X
X X
X X
X X
X X
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Now, consider what needs to be done to this shape to turn it from being
a large rectangle into the first shape making up the word. It will be
something like this:-
1) rotate it 90 degrees (anti-clockwise is positive)
2) translate it right a little (the width of the rectangle)
3) shrink it (scale it) so that it is only as high as the
original rectangle's width.
The other transformations can similarly be detirmined.
Once this is done, the process begins where each transformation is
allowed to transform an original shape. (NOTE: It could be ANY shape
except the 'homogeneous' one (ie: empty, blank shape).
In my case the original shae is just a rectangle.
The transformations process this shape and produce a new shape.
This new shape is fed back into the transformations again and again
until the final fractal emerges.
This technique can be applied to more shapes than the word NICK.
Fractal ferns, trees mountain ranges can also be made by the same
process. Simply imagine the rough shape of the final image- fern, leaf
or what not, and then construct it with linear tranformations of
itself. Incidently, this process is described in a technical way by
the "Collage Theorem"- laid out in the book "Fractals Eveywhere".
Another source of information I used was "Computer Graphics"
by Hearn & Baker which described in great detail the use of matrices
in transforming points in space- in 3 dimensions as well as two.
*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <exec/types.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <proto/all.h>
#define LIB_REV 33
#define XOFF 0
#define YOFF 100
#define WHITE 1
#define BLACK 0
#define _HIRES_WIDTH 640
#define _HIRES_HEIGHT 512
#define _LORES_WIDTH 320
#define _LORES_HEIGHT 256
#define BORDERTHICK 10
#define BOOL unsigned char
#define UBYTE unsigned char
#define USHORT unsigned short int
#define MATRIXTYPE float
#define XONE (MATRIXTYPE)(1)
#define xmul(x, y) ((x) * (y))
#define xcos(x) (cos((double)x))
#define rtod(x) ((x) * 57.296) /* rads to degrees */
#define dtor(x) ((x) * 0.01745) /* degrees to rads */
#define xsin(x) (sin((double)x))
#define xtof(x) (double)(x)
#define NO_TRANSFORMS 13
#define PLANE_COLS (640)
#define PLANE_ROWS ((unsigned int)((double)(PLANE_COLS) * ((double)55 / (double)174)))
#define MAX(x, y) ((x > y) ? (x) : (y))
#define MIN(x, y) ((x < y) ? (x) : (y))
/* prototypes */
VOID kill_mtx(struct matrix *);
VOID kill_bit_plane(struct bit_plane *);
BOOL init_mtx(struct matrix *, unsigned int, unsigned int);
BOOL init_bit_plane(struct bit_plane *, unsigned int, unsigned int);
BOOL copy_bit_plane(struct bit_plane *, struct bit_plane *);
BOOL copy_mtx(struct matrix *, struct matrix *);
BOOL clr_bit_plane(struct bit_plane *);
BOOL within_mtx(struct matrix *, unsigned int, unsigned int);
BOOL within_bit_plane(struct bit_plane *, unsigned int, unsigned int);
BOOL assn_mtx(struct matrix *, unsigned int, unsigned int, MATRIXTYPE);
BOOL assn_bit_plane(struct bit_plane *, unsigned int, unsigned int, BOOL);
BOOL valu_bit_plane(struct bit_plane *, unsigned int, unsigned int);
MATRIXTYPE valu_mtx(struct matrix *, unsigned int, unsigned int);
VOID prin_bit_plane(struct bit_plane *);
VOID fill_mtx(struct matrix *, MATRIXTYPE []);
VOID prin_bit_plane(struct bit_plane *);
VOID prin_mtx(struct matrix *);
VOID load_plane_matrix(struct RastPort *, struct bit_plane *);
struct matrix *mul_mtx(struct matrix *, struct matrix *);
struct matrix *id_mtx(unsigned int);
struct matrix *shear_mtx(double, double);
struct matrix *scale_mtx(double, double);
struct matrix *rot_mtx(double);
struct matrix *xlate_mtx(double, double);
VOID clr_screen(VOID);
VOID OpenAll(VOID);
VOID plot(struct Window *, USHORT, USHORT, USHORT);
VOID openViewing(VOID);
VOID closeViewing(VOID);
VOID clean_exit(int);
VOID setColours(VOID);
VOID setColours(VOID);
VOID main(VOID);
struct matrix {
MATRIXTYPE *table;
unsigned int rows, cols;
};
/* Most calculations for the affine transformations are done with
this 'matrix' type, since this makes linear transformations relatively
easy to perform */
struct bit_plane {
UBYTE *table;
unsigned int rows, cols;
};
/* A 'bit-plane' is a "flash" name for a two dimensional array of BOOLEAN
values- stored as bits so as to make them as memory efficient as possible.
Whereas with matrices operations may include addition, subtraction etc,
bit-planes can be subject to logical ANDs, ORs etc. */
#define NULL_MATRIX { NULL, 0, 0 } /* NULL matrix definition for
global matrices */
/* globals */
/* The following matrices are used internally to return matrix values from
specific functions. At the end of the program, they are killed off by
the routine 'cleanExit' so as to give back all memory allocated by
AmigaDOS */
struct matrix prod_1 = NULL_MATRIX;
struct matrix prod_2 = NULL_MATRIX; /* used by mul_mtx */
struct matrix id = NULL_MATRIX; /* identity matrix */
struct matrix scl = NULL_MATRIX; /* a scaling matrix */
struct matrix shr = NULL_MATRIX; /* a shearing matrix */
struct matrix xlt = NULL_MATRIX; /* a translation matrix */
struct matrix rot = NULL_MATRIX; /* a rotation matrix */
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;
struct Window *window = NULL;
struct Screen *screen = NULL;
struct RastPort *rp = NULL;
struct ViewPort *vp = NULL;
struct IntuiMessage *msg;
struct bit_plane s, t;
struct matrix aff_mtx[NO_TRANSFORMS];
struct matrix u, *v;
VOID main(VOID)
{
int x, y;
unsigned int i, j;
unsigned int h, k;
/* The two grids that the fractals is drawn into */
init_bit_plane(&s, PLANE_ROWS, PLANE_COLS);
init_bit_plane(&t, PLANE_ROWS, PLANE_COLS);
/* reserve space for the affine transformations */
for (i = 0; i < NO_TRANSFORMS; i++)
init_mtx(&aff_mtx[i], 3, 3);
/* Must have a 1 in position [1,3] of the point vector when doing
any sort of linear transformation. (Might as well do it here once
than millions of times in the loop below) */
init_mtx(&u, 1, 3);
assn_mtx(&u, 1, 3, XONE);
/* the matrices below are the three transformations needed to draw the
'famous' Sierpinski Triangle */
/*copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
mul_mtx(xlate_mtx((double)(0.5) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
),
&aff_mtx[0]);
copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
mul_mtx(xlate_mtx((double)0, (double)(0.5) * (double)PLANE_ROWS),
id_mtx(3)
)
),
&aff_mtx[1]);
copy_mtx(mul_mtx(scale_mtx((double)(0.5), (double)(0.5)),
mul_mtx(xlate_mtx((double)0, (double)0),
id_mtx(3)
)
),
&aff_mtx[2]);*/
/* below are the affine transformations for the NICK fractal */
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(xlate_mtx((double)PLANE_ROWS, (double)0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
id_mtx(3)
)
)
),
&aff_mtx[0]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.1455), (double)(0.2041)),
mul_mtx(shear_mtx((double)0, (double)(-2.3750)),
mul_mtx(xlate_mtx((double)(0.4727) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
)
),
&aff_mtx[1]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
mul_mtx(xlate_mtx((double)(0.8000) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[2]);
copy_mtx(mul_mtx(scale_mtx((double)(0.1021), (double)(0.2727)),
mul_mtx(xlate_mtx((double)(0.9455) * (double)PLANE_ROWS, (double)(0.7273) * (double)PLANE_ROWS),
id_mtx(3)
)
),
&aff_mtx[3]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.2041)),
mul_mtx(xlate_mtx((double)(1.2727) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[4]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
mul_mtx(xlate_mtx((double)(1.7455) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[5]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.1455), (double)(0.0851)),
mul_mtx(xlate_mtx((double)(1.8909) * (double)PLANE_ROWS, (double)(0.7273) * (double)PLANE_ROWS),
id_mtx(3)
)
)
),
&aff_mtx[6]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.1455), (double)(0.0851)),
mul_mtx(xlate_mtx((double)(1.8909) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[7]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
mul_mtx(xlate_mtx((double)(2.2182) * (double)PLANE_ROWS, (double)(0.6545) * (double)PLANE_ROWS),
id_mtx(3)
)
)
),
&aff_mtx[8]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
mul_mtx(xlate_mtx((double)(2.2182) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[9]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.3119)),
mul_mtx(xlate_mtx((double)(2.6909) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
),
&aff_mtx[10]);
copy_mtx(mul_mtx(rot_mtx((double)-90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.1078)),
mul_mtx(shear_mtx((double)(0.4210), (double)0),
mul_mtx(xlate_mtx((double)(2.8363) * (double)PLANE_ROWS, (double)PLANE_ROWS),
id_mtx(3)
)
)
)
),
&aff_mtx[11]);
copy_mtx(mul_mtx(rot_mtx((double)90.0),
mul_mtx(scale_mtx((double)(0.3273), (double)(0.2041)),
mul_mtx(shear_mtx((double)(-0.2222), (double)0),
mul_mtx(xlate_mtx((double)(3.1636) * (double)PLANE_ROWS, (double)0),
id_mtx(3)
)
)
)
),
&aff_mtx[12]);
OpenAll(); /* open graphics screen etc */
/* draw the original shape - a rectangle around the border of the
transformed region */
SetAPen(rp, WHITE);
Move(rp, 0 + XOFF, 0 + YOFF);
Draw(rp, PLANE_COLS + XOFF - 1, 0 + YOFF);
Draw(rp, PLANE_COLS + XOFF - 1, PLANE_ROWS + YOFF - 1);
Draw(rp, 0 + XOFF, PLANE_ROWS + YOFF - 1);
Draw(rp, 0 + XOFF, 0 + YOFF);
/* load the original shape into a 'bit-plane' */
load_plane_matrix(rp, &t);
for (h = 1; h <= 8; h++) { /* transform shape 8 times */
for (i = 1; i <= PLANE_ROWS; i++) /* top to bottom */
for (j = 1; j <= PLANE_COLS; j++) { /* left to right */
if (window->UserPort->mp_SigBit) { /* pressed the CLOSEWINDOW button? */
msg = (struct IntuiMessage *)GetMsg(window->UserPort);
if (msg->Class == CLOSEWINDOW)
clean_exit(RETURN_OK);
}
plot(window, (USHORT)((j - 1) + XOFF), (USHORT)(YOFF + PLANE_ROWS - i), WHITE);
if (valu_bit_plane(&t, i, j))
/* if there is something to transform do it with all
NO_TRANSFORMS transformations */
for (k = 0; k < NO_TRANSFORMS; k++) {
assn_mtx(&u, 1, 1, (MATRIXTYPE)j);
assn_mtx(&u, 1, 2, (MATRIXTYPE)i);
v = mul_mtx(&u, &aff_mtx[k]);
x = (int)valu_mtx(v, 1, 1);
y = (int)valu_mtx(v, 1, 2);
if ((x >= 1) && (x <= PLANE_COLS) &&
(y >= 1) && (y <= PLANE_ROWS))
assn_bit_plane(&s, (unsigned int)(y), (unsigned int)(x), TRUE);
}
}
copy_bit_plane(&s, &t);
/* make new shape the old shape for next time around */
clr_bit_plane(&s); /* clear the new shape */
clr_screen(); /* clear screen */
/* show the results of last transformations */
for (i = 1; i <= PLANE_ROWS; i++)
for (j = 1; j <= PLANE_COLS; j++)
if (valu_bit_plane(&t, i, j))
plot(window, (USHORT)((j - 1) + XOFF), (USHORT)(YOFF + PLANE_ROWS - i), WHITE);
}
/* all transformations are done, so wait forever for the user to close
the window */
while (TRUE) {
Wait(1 << window->UserPort->mp_SigBit);
msg = (struct IntuiMessage *)GetMsg(window->UserPort);
if (msg->Class == CLOSEWINDOW)
clean_exit(RETURN_OK);
}
}
BOOL init_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
/* set up a matrix of given dimensions */
{
unsigned int size;
if ((r >= 1) && (c >= 1)) {
mtx->rows = r;
mtx->cols = c;
size = r * c;
mtx->table = calloc(size, sizeof(MATRIXTYPE));
return (TRUE);
}
else
return (FALSE);
}
BOOL init_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
/* set up a bit plane of given dimensions */
{
unsigned int size;
if ((r >= 1) && (c >= 1)) {
mtx->rows = r;
mtx->cols = c;
size = r * ((c >> 3) + 1);
mtx->table = calloc(size, sizeof(UBYTE));
if (mtx->table)
return (TRUE);
else
return (FALSE);
}
else
return (FALSE);
}
BOOL copy_bit_plane(struct bit_plane *src, struct bit_plane *des)
/* copy one bit plane to another */
{
UBYTE *j;
unsigned int i, size;
if ((src->rows == des->rows) && (src->cols == des->cols) &&
(src->rows >= 1) && (src->cols >= 1) &&
(src->table) && (des->table)) {
size = src->rows * ((src->cols >> 3) + 1);
j = src->table;
for (i = 0; i < size; i++, j++)
*(des->table + i) = *j;
return (TRUE);
}
else
return (FALSE);
}
BOOL clr_bit_plane(struct bit_plane *mtx)
/* assign all FALSE values to each element of a bit plane */
{
unsigned int i, size;
if ((mtx->rows >= 1) && (mtx->cols >= 1) &&
(mtx->table)) {
size = mtx->rows * ((mtx->cols >> 3) + 1);
for (i = 0; i < size; i++)
*(mtx->table + i) = 0;
return (TRUE);
}
else
return (FALSE);
}
VOID kill_mtx(struct matrix *mtx)
/* redeem memory allocated to a matrix */
{
if (mtx->table)
free(mtx->table);
mtx->table = NULL;
mtx->rows = 0;
mtx->cols = 0;
}
VOID kill_bit_plane(struct bit_plane *mtx)
/* redeem all memory allocated to a bit plane */
{
if (mtx->table)
free(mtx->table);
mtx->table = NULL;
mtx->rows = 0;
mtx->cols = 0;
}
BOOL copy_mtx(struct matrix *src, struct matrix *des)
/* copy one matrix to another */
{
MATRIXTYPE *j;
unsigned int i, size;
if ((src->rows == des->rows) && (src->cols == des->cols)) {
size = src->rows * src->cols;
j = src->table;
for (i = 0; i < size; i++, j++)
*(des->table + i) = *j;
return TRUE;
}
else
return FALSE;
}
BOOL within_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
/* return whether or not the element described is in a the matrix given */
{
if ((r >= 1) && (c >= 1) && (r <= mtx->rows) && (c <= mtx->cols))
return (TRUE);
else
return (FALSE);
}
BOOL within_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
/* return whether or not the element described is in a the bit plane given */
{
if ((r >= 1) && (c >= 1) && (r <= mtx->rows) && (c <= mtx->cols))
return (TRUE);
else
return (FALSE);
}
BOOL assn_mtx(struct matrix *mtx, unsigned int r, unsigned int c, MATRIXTYPE data)
/* assign a value to a matrix */
{
if (within_mtx(mtx, r, c)) {
*(mtx->table + mtx->cols * (r - 1) + (c - 1)) = data;
return (TRUE);
}
else
return (FALSE);
}
BOOL assn_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c, BOOL value)
/* assign a logical value to a bit plane */
{
UBYTE *location;
if (within_bit_plane(mtx, r, c)) {
location = mtx->table +
(r - 1) * ((mtx->cols >> 3) + 1) + ((c - 1) >> 3);
if (value)
*location |= 1 << (0x0007 & (c - 1));
else
*location &= ~(1 << (0x0007 & (c - 1)));
return (TRUE);
}
else
return (FALSE);
}
BOOL valu_bit_plane(struct bit_plane *mtx, unsigned int r, unsigned int c)
/* return the element asked for of the matrix given */
{
UBYTE *location;
location = mtx->table +
(r - 1) * ((mtx->cols >> 3) + 1) + ((c - 1) >> 3);
return (BOOL)(*location & (1 << (0x0007 & (c - 1))) );
}
VOID prin_bit_plane(struct bit_plane *mtx)
/* display the contents of a bit plane */
{
unsigned int i, j;
for (i = 1; i <= mtx->rows; i++) {
for (j = 1; j <= mtx->cols; j++)
printf("%s", ((valu_bit_plane(mtx, i, j)) ? ("##") : (" ")));
printf("\n");
}
printf("\n");
}
struct matrix *mul_mtx(struct matrix *mtx1, struct matrix *mtx2)
/* FUNCTIONALLY return the product of two matrices (not a procedure!) */
{
unsigned int i, j, k;
MATRIXTYPE op_1, op_2, sum;
struct matrix *prod, *temp_store;
if (mtx1->cols == mtx2->rows) {
if (prod_1.table) {
temp_store = &prod_1;
prod = &prod_2;
}
else {
temp_store = &prod_2;
prod = &prod_1;
}
init_mtx(prod, mtx1->rows, mtx2->cols);
for (k = 0; k < mtx1->rows; k++) {
for (j = 0; j < mtx2->cols; j++) {
sum = 0;
for (i = 0; i < mtx1->cols; i++) {
op_1 = *(mtx2->table + mtx2->cols * i + j);
op_2 = *(mtx1->table + mtx1->cols * k + i);
if (op_2 != 0)
if (op_2 == XONE)
sum += op_1;
else
sum += xmul(op_1, op_2);
}
*(prod->table + mtx2->cols * k + j) = sum;
}
}
if (temp_store->table)
kill_mtx(temp_store);
return (prod);
}
else
return ((struct matrix *)(NULL));
}
VOID fill_mtx(struct matrix *mtx, MATRIXTYPE data[])
/* a convenience procedure to fill a matrix with the conents of an array */
{
unsigned int i, size;
size = mtx->rows * mtx->cols;
for (i = 0; i < size; i++)
*(mtx->table + i) = data[i];
}
MATRIXTYPE valu_mtx(struct matrix *mtx, unsigned int r, unsigned int c)
/* return the value of a matrix */
{
if (within_mtx(mtx, r, c))
return *(mtx->table + mtx->cols * (r - 1) + (c - 1));
else
return (FALSE);
}
VOID prin_mtx(struct matrix *mtx)
/* display the contents of a matrix */
{
unsigned int i, j;
for (j = 1; j <= mtx->rows; j++) {
for (i = 1; i <= mtx->cols; i++)
printf("%2.4lf ", xtof(valu_mtx(mtx, j, i)));
printf("\n");
}
printf("\n");
}
struct matrix *id_mtx(unsigned int size)
/* return the identity matrix of the size specified:
1 0 0 0
0 1 0 0 (This is the identity matrix of size 4)
0 0 1 0
0 0 0 1
*/
{
unsigned int i;
if (size >= 1) {
kill_mtx(&id);
init_mtx(&id, size, size);
for (i = 1; i <= size; i++)
assn_mtx(&id, i, i, XONE);
return (&id);
}
else
return ((struct matrix *)(NULL));
}
struct matrix *shear_mtx(double shear_x, double shear_y)
/* return the matrix used to shear point vectors */
{
if (!shr.table) {
init_mtx(&shr, 3, 3);
copy_mtx(id_mtx(3), &shr);
}
assn_mtx(&shr, 2, 1, (MATRIXTYPE)shear_x);
assn_mtx(&shr, 1, 2, (MATRIXTYPE)shear_y);
return (&shr);
}
struct matrix *scale_mtx(double scale_x, double scale_y)
/* return the matrix used to scale vectors */
{
if (!scl.table) {
init_mtx(&scl, 3, 3);
copy_mtx(id_mtx(3), &scl);
}
assn_mtx(&scl, 1, 1, (MATRIXTYPE)scale_x);
assn_mtx(&scl, 2, 2, (MATRIXTYPE)scale_y);
return (&scl);
}
struct matrix *rot_mtx(double degs)
/* return the matrix used to rotate vectors */
{
if (!rot.table) {
init_mtx(&rot, 3, 3);
copy_mtx(id_mtx(3), &rot);
}
assn_mtx(&rot, 1, 1, (MATRIXTYPE)( xcos(dtor(degs))));
assn_mtx(&rot, 1, 2, (MATRIXTYPE)( xsin(dtor(degs))));
assn_mtx(&rot, 2, 1, (MATRIXTYPE)(-xsin(dtor(degs))));
assn_mtx(&rot, 2, 2, (MATRIXTYPE)( xcos(dtor(degs))));
return (&rot);
}
struct matrix *xlate_mtx(double d_x, double d_y)
/* return the matrix used to translate vectors */
{
if (!xlt.table) {
init_mtx(&xlt, 3, 3);
copy_mtx(id_mtx(3), &xlt);
}
assn_mtx(&xlt, 3, 1, (MATRIXTYPE)d_x);
assn_mtx(&xlt, 3, 2, (MATRIXTYPE)d_y);
return (&xlt);
}
VOID clr_screen(VOID)
{
SetAPen(rp, BLACK);
RectFill(rp, 0, 10, screen->Width - 1, screen->Height - 1);
}
VOID load_plane_matrix(struct RastPort *rp, struct bit_plane *t)
{
unsigned int i, j;
for (i = 1; i <= PLANE_ROWS; i++) {
if (window->UserPort->mp_SigBit) { /* pressed the CLOSEWINDOW button? */
msg = (struct IntuiMessage *)GetMsg(window->UserPort);
if (msg->Class == CLOSEWINDOW)
clean_exit(RETURN_OK);
}
for (j = 1; j <= PLANE_COLS; j++)
assn_bit_plane(t, i, j, (BOOL)(ReadPixel(rp, (j - 1 + XOFF), (YOFF + PLANE_ROWS - i))));
}
}
VOID OpenAll(VOID)
{
printf("* NICK Fractal *\n");
printf("by Dave Lyneham, 1991.\n");
printf("This program draws a fractal\n");
printf("word (NICK) but it takes\n");
printf("a long time. (~2 hours)\n\n");
printf("CLICK THE CLOSEWINDOW GADGET\nTO ABORT THE PROGRAM");
IntuitionBase = (struct IntuitionBase *)
OpenLibrary("intuition.library", LIB_REV);
if (IntuitionBase == NULL)
clean_exit(RETURN_WARN);
GfxBase = (struct GfxBase *)
OpenLibrary("graphics.library", LIB_REV);
if (GfxBase == NULL)
clean_exit(RETURN_WARN);
openViewing();
}
VOID plot(struct Window *Window, USHORT x, USHORT y, USHORT pen)
{
if ((x <= Window->Width) && (y <= Window->Height) && (x >= 0) && (y >= BORDERTHICK)) {
SetAPen(Window->RPort, pen);
WritePixel(Window->RPort, x, y);
}
}
VOID openViewing(VOID)
{
struct NewScreen NewScreen = {
0, 0,
0, 0,
1,
1, 0,
NULL,
CUSTOMSCREEN,
NULL,
NULL,
NULL,
NULL,
};
struct NewWindow NewWindow = {
0, 1,
0, 0,
1, 0,
CLOSEWINDOW,
WINDOWCLOSE | ACTIVATE,
NULL,
NULL,
NULL,
NULL,
NULL,
0, 0,
-1, -1,
CUSTOMSCREEN
};
NewScreen.Width = _HIRES_WIDTH;
NewScreen.Height = _HIRES_HEIGHT;
NewScreen.ViewModes = LACE | HIRES;
screen = (struct Screen *)OpenScreen(&NewScreen);
if (screen == NULL)
clean_exit(RETURN_WARN);
NewWindow.Screen = screen;
NewWindow.Width = screen->Width;
NewWindow.Height = screen->Height - 1;
window = (struct Window *)OpenWindow(&NewWindow);
if (window == NULL)
clean_exit(RETURN_WARN);
rp = window->RPort;
vp = (struct ViewPort *)ViewPortAddress(window);
SetDrMd(rp, JAM2);
setColours();
}
VOID closeViewing()
{
if (window)
CloseWindow(window);
if (screen)
CloseScreen(screen);
}
VOID clean_exit(int returnValue)
{
unsigned int i;
kill_bit_plane(&s);
kill_bit_plane(&t);
for (i = 0; i < NO_TRANSFORMS; i++)
kill_mtx(&aff_mtx[i]);
kill_mtx(&u);
kill_mtx(&prod_1);
kill_mtx(&prod_2);
kill_mtx(&id);
kill_mtx(&scl);
kill_mtx(&shr);
kill_mtx(&xlt);
kill_mtx(&rot);
closeViewing();
if (GfxBase)
CloseLibrary((struct Library *)GfxBase);
if (IntuitionBase)
CloseLibrary((struct Library *)IntuitionBase);
if (returnValue != RETURN_OK)
DisplayBeep(NULL);
exit(returnValue);
}
VOID setColours(VOID)
{
SetRGB4(vp, BLACK, 0, 0, 0);
SetRGB4(vp, WHITE, 15, 15, 15);
SetAPen(rp, BLACK);
RectFill(rp, 0, 10, screen->Width - 1, screen->Height - 1);
}